/*
 * Copyright (C) 2007-2008  Hylke van der Schaaf
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, in version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package hextd.map;

import com.twolattes.json.Entity;
import com.twolattes.json.Value;
import com.usoog.tdcore.exception.InsufficientResourcesException;
import com.usoog.tdcore.exception.NoSuchTileException;
import com.usoog.tdcore.exception.TileAlreadyHasTowerException;
import com.usoog.tdcore.exception.TileNotBuildableException;
import com.usoog.tdcore.gamestate.GameState;
import com.usoog.tdcore.player.Player;
import com.usoog.tdcore.player.Resources;
import hextd.core.GameGridImplementation;
import hextd.core.GameStateImplementation;
import hextd.hex.HexTile;
import hextd.tower.FactoryTower;
import hextd.tower.HexTDTower;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;

@Entity
public class JsonTower {

	public static enum optionKey {

		s0("Target Lock (0=off, 1=on)", "0"),
		s1("Targeting policy (0=close, 3=furthest)", "0"),
		s2("Firecontrol sync (0=same, 1=diff)", "0"),
		u("Number of upgrades", "0"),
		maxlevel("Maximum level", "10"),
		budget("Starting budget", "100"),
		incomedelay("# of ticks between income", "50"),
		incomefactor("Fraction of income received", "0.25"),
		incomestart("Starting income", "10"),
		creeptypes("Used creep types (0=rr, 8=hh)", "0,1,2,3"),
		creepticks("# of ticks per creep type", "600"),
		creepsizes("Used creep sizes (0=N, 1=S, 2=L)", "0,1,2");
		public final String description;
		public final String defaultValue;

		private optionKey(String description, String defaultValue) {
			this.description = description;
			this.defaultValue = defaultValue;
		}
	}
	@Value
	public int row;
	@Value
	public int col;
	@Value
	public FactoryTower.type type;
	@Value(optional = true)
	public Map<String, String> options;
//
	private JsonTowerPanel settingsPanel;

	@Override
	public String toString() {
		return type.toString() + " (" + row + "," + col + ")";
	}

	public JPanel getSettingsPanel() {
		if (settingsPanel == null) {
			settingsPanel = new JsonTowerPanel(this);
		}
		return settingsPanel;
	}

	public void loadTower(Player owner, GameStateImplementation target) {
		GameStateImplementation gs = (GameStateImplementation) target;
		GameGridImplementation gameGrid = (GameGridImplementation) target.getGameGrid();

		Map<String, Long> tempCostMap = null;
		try {
			HexTile h = gameGrid.getTile(col, row);
			if (!h.hasTower()) {
				HexTDTower newTower;
				Player tOwner = owner;
				try {
					newTower = FactoryTower.createTower(type, target, h, tOwner, GameState.actionDelay);
					target.addTower(newTower);
					Resources resources = tOwner.getResources();
					if (!resources.canQueue(type.price)) {
						resources.doReceive(type.price);
					}
					resources.queuePayment(type.price);
					if (options != null) {
						for (Entry<String, String> e : options.entrySet()) {
							JsonTower.optionKey key = JsonTower.optionKey.valueOf(e.getKey().toLowerCase());
							switch (key) {
								case s0:
									newTower.setMode(1, "0", e.getValue());
									break;

								case s1:
									newTower.setMode(1, "1", e.getValue());
									break;

								case s2:
									newTower.setMode(1, "2", e.getValue());
									break;

								case u:
									int times = Integer.parseInt(e.getValue());
									for (int i = 0; i < times; i++) {
										tempCostMap = newTower.getUpgradeCost("", true, tempCostMap);
										resources.doReceive(tempCostMap);
										try {
											newTower.upgrade(GameStateImplementation.actionDelay, null);
										} catch (InsufficientResourcesException ex) {
											Logger.getLogger(GameMapImplementation.class.getName()).log(Level.SEVERE, null, ex);
										}
									}
									break;

								default:
									newTower.setSetting(key, e.getValue());
									break;
							}
						}
					}
				} catch (TileAlreadyHasTowerException ex) {
					Logger.getLogger(GameMapImplementation.class.getName()).log(Level.SEVERE, null, ex);
				} catch (TileNotBuildableException ex) {
					Logger.getLogger(GameMapImplementation.class.getName()).log(Level.SEVERE, null, ex);
				}

			}
		} catch (NoSuchTileException ex) {
			Logger.getLogger(GameMapImplementation.class.getName()).log(Level.SEVERE, null, ex);
		}
	}
}
